package com.hsu.hsurpc.loadbalancer;

import com.hsu.hsurpc.spi.SpiLoader;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 负载均衡工厂（工厂模式，用于获取负载均衡器对象）
 * @Author Hsu琛君珩
 * @Date 2024-09-24 15:54
 * @Description
 * @Version: v1.0.0
 */
public class LoadBalancerFactory {

    /**
     * 存储各个负载均衡器实例的 Map，使用线程安全的 ConcurrentHashMap
     * 用于缓存不同类型的负载均衡器实例，以避免重复创建，提高性能。
     */
    private static final Map<String, LoadBalancer> KEY_LOAD_BALANCER_MAP = new ConcurrentHashMap<>();

    /**
     * 默认负载均衡器
     * 当指定的键名无法匹配任何负载均衡器时，使用默认的轮询负载均衡器。
     */
    private static final LoadBalancer DEFAULT_LOAD_BALANCER = new LeastActiveLoadBalancer();

    /**
     * 获取负载均衡器实例，使用懒加载方式，只有在首次请求时创建实例
     * 如果负载均衡器实例不存在于缓存中，则通过 createLoadBalancer 方法动态创建。
     *
     * @param key 负载均衡器名称（如 "roundRobin", "random", "consistentHash"）
     * @return 负载均衡器实例，如果实例不存在则根据键名创建一个新的实例
     */
    public static LoadBalancer getInstance(String key) {
        // 从 Map 中获取已有实例，如果不存在则进行创建
        return KEY_LOAD_BALANCER_MAP.computeIfAbsent(key, LoadBalancerFactory::createLoadBalancer);
    }

    /**
     * 创建负载均衡器实例的方法，通过 SPI 动态加载指定的负载均衡器
     * 如果通过 SPI 加载的实例为空，则返回默认的负载均衡器。
     *
     * @param key 负载均衡器名称
     * @return 创建好的负载均衡器实例，如果未找到则返回默认的负载均衡器
     */
    private static LoadBalancer createLoadBalancer(String key) {
        // 使用 SPI Loader 动态加载负载均衡器
        LoadBalancer loadBalancer = SpiLoader.getInstance(LoadBalancer.class, key);
        return (loadBalancer != null) ? loadBalancer : DEFAULT_LOAD_BALANCER;
    }
}
